package com.p2p.front.service.impl;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.p2p.base.constents.InnerAccountConsts;
import com.p2p.base.model.Money;
import com.p2p.base.page.PageVo;
import com.p2p.base.service.ProducerService;
import com.p2p.base.util.DateUtil;
import com.p2p.front.dal.dao.LoanRepayDao;
import com.p2p.front.dal.model.LoanInfo;
import com.p2p.front.dal.model.LoanRepay;
import com.p2p.front.dal.model.LoanVariation;
import com.p2p.front.dal.model.TenderReturn;
import com.p2p.front.enums.LoanRepayMethod;
import com.p2p.front.result.LoanRepayResult;
import com.p2p.front.result.TenderReturnResult;
import com.p2p.front.service.ChargeService;
import com.p2p.front.service.LoanInfoService;
import com.p2p.front.service.LoanRepayService;
import com.p2p.front.service.LoanVariationService;
import com.p2p.front.service.TenderReturnService;
import com.p2p.front.service.TenderService;
import com.p2p.front.util.LoanRepayUtil;
import com.p2p.front.util.RateUtil;
import com.p2p.front.web.form.TenderRepayForm;
import com.p2p.trans.client.enums.SubTransCodeEnum;
import com.p2p.trans.client.enums.TransCodeEnum;
import com.p2p.trans.client.facade.AccountQueryFacade;
import com.p2p.trans.client.facade.AccountTransFacade;
import com.p2p.trans.client.model.TransInfo;
import com.p2p.trans.client.result.AccountQueryResult;
import com.p2p.trans.client.result.AccountTransResult;

/**
 * @author ruiqi
 *
 */
@Service("loanRepayService")
public class LoanRepayServiceImpl implements LoanRepayService {

	protected final Logger logger = LoggerFactory.getLogger(LoanRepayServiceImpl.class);
	
	@Resource
	private LoanRepayDao loanRepayDao;
	
	@Resource
	protected LoanInfoService loanInfoService;
	
	@Resource
	private LoanVariationService loanVariationService;
	
	@Resource
	protected AccountTransFacade accountTransFacade;
	
	@Resource
	protected AccountQueryFacade accountQueryFacade;
	
	@Resource
	protected TenderReturnService tenderReturnService;
	
	@Resource
	protected TenderService tenderService;
	
	@Resource
	private ProducerService producerService;
	
	@Resource
	private PlatformTransactionManager transactionManager;
	
	@Resource
	private ChargeService chargeService;
	
	@Override
	public void createRepay(LoanRepay loanRepay) {
		loanRepayDao.create(loanRepay);
	}

	
	@Override
	public void create(LoanInfo loanInfo, LoanVariation loanVariation) {
		Money zero = new Money();
		String str = loanInfo.getRepayMethod();
		LoanRepayMethod repayMethod = LoanRepayMethod.getEnumByName(str);
		//Calendar calendar = Calendar.getInstance();
		Date now = new Date();
		
		List<LoanRepay> list = new ArrayList<LoanRepay>();
		
		if(repayMethod==LoanRepayMethod.m){
			Money loanFee= new Money((long)(loanVariation.getTenderAmount().getCent()*loanInfo.getMfeeRate()));
			Money monthRepay = RateUtil.getMonthRepayAmountForPrincipalAndInterest(loanInfo.getApr(), loanInfo.getDeadline(), loanVariation.getTenderAmount());
			Money monthPrincipal = new Money(loanVariation.getTenderAmount().getCent()/loanInfo.getDeadline());
			Money tempAllRepay = new Money();
			Money tempAllRepayPrincipal = new Money();
			for(int i=1;i<=loanInfo.getDeadline();i++){
				
				LoanRepay loanRepay = new LoanRepay();
				loanRepay.setLid(loanVariation.getLoanId());
				loanRepay.setUid(loanInfo.getUid());
				
				loanRepay.setLateFee(zero);
				loanRepay.setEarly(0);
				loanRepay.setPicurl("");
				loanRepay.setLateurl("");
				loanRepay.setStatus(11);
				loanRepay.setOstatus(11);
				
				loanRepay.setOktime(null);
				
				
				
				loanRepay.setRepayAmount(monthRepay);
				loanRepay.setPrincipal(monthPrincipal);
				
				loanRepay.setNo(i);
				
				Date date = DateUtil.addMonth(now, i);
				Date startTime = DateUtil.addMonth(now, i-1);
				loanRepay.setStartTime(startTime);
				loanRepay.setTime(date);
				loanRepay.setPaytime(null);
				loanRepay.setUptime(now);
				//loanRepay.setReturnAmount(returnAmount);
				//loanRepay.setReturnPrincipal(returnPrincipal);
				loanRepay.setLoanFee(loanFee);
				
				if(i==loanInfo.getDeadline()){
					loanRepay.setPrincipal(new Money(loanVariation.getTenderAmount().getCent()-tempAllRepayPrincipal.getCent()));
				}
				tempAllRepay.add(monthRepay);
				tempAllRepayPrincipal.add(monthPrincipal);
				list.add(loanRepay);
			}
			
		
		}else if(repayMethod==LoanRepayMethod.i){
			Money loanfee = new Money((long)(loanVariation.getTenderAmount().getCent()*(loanInfo.getMfeeRate()/100)));
			
			Money monthRepay = RateUtil.getMonthInterestForNormal(loanInfo.getApr(), loanInfo.getDeadline(), loanVariation.getTenderAmount());
			
			Money tempAllRepay = new Money();
			Money monthPrincipal = new Money();
			Money tempAllRepayPrincipal = new Money();
			for(int i=1;i<=loanInfo.getDeadline();i++){
				LoanRepay loanRepay = new LoanRepay();
				loanRepay.setLid(loanVariation.getLoanId());
				loanRepay.setUid(loanInfo.getUid());
				
				loanRepay.setLateFee(zero);
				loanRepay.setEarly(0);
				loanRepay.setPicurl("");
				loanRepay.setLateurl("");
				loanRepay.setStatus(11);
				loanRepay.setOstatus(11);
				
				loanRepay.setOktime(null);
				
				
				loanRepay.setRepayAmount(monthRepay);
				loanRepay.setPrincipal(monthPrincipal);
				
				
				loanRepay.setNo(i);
				
				Date date = DateUtil.addMonth(now, i);
				Date startTime = DateUtil.addMonth(now, i-1);
				loanRepay.setStartTime(startTime);
				loanRepay.setTime(date);
				loanRepay.setPaytime(null);
				loanRepay.setUptime(now);
				//loanRepay.setReturnAmount(returnAmount);
				//loanRepay.setReturnPrincipal(returnPrincipal);
				loanRepay.setLoanFee(loanfee);
				
				if(i==loanInfo.getDeadline()){
					loanRepay.setPrincipal(new Money(loanVariation.getTenderAmount().getCent()-tempAllRepayPrincipal.getCent()));
					loanRepay.setRepayAmount(new Money(loanRepay.getPrincipal().getCent()+loanRepay.getRepayAmount().getCent()));
				}
				
				tempAllRepay.add(monthRepay);
				tempAllRepayPrincipal.add(monthPrincipal);
				list.add(loanRepay);
			}
		}else if(repayMethod==LoanRepayMethod.e){
			Money loanfee = new Money((long)(loanVariation.getTenderAmount().getCent()*loanInfo.getMfeeRate()));
			Money allInterestRepay = RateUtil.getAllInterestForNormal(loanInfo.getApr(), loanInfo.getDeadline(), loanVariation.getTenderAmount());
			
			Money tempAllRepay = new Money(loanVariation.getTenderAmount().getCent()+allInterestRepay.getCent());
			//Money monthPrincipal = new Money();
			
			LoanRepay loanRepay = new LoanRepay();
			loanRepay.setLid(loanVariation.getLoanId());
			loanRepay.setUid(loanInfo.getUid());
			
			loanRepay.setLateFee(zero);
			loanRepay.setEarly(0);
			loanRepay.setPicurl("");
			loanRepay.setLateurl("");
			loanRepay.setStatus(11);
			loanRepay.setOstatus(11);
			
			loanRepay.setOktime(null);
			
			
			loanRepay.setRepayAmount(tempAllRepay);
			loanRepay.setPrincipal(loanVariation.getTenderAmount());
			
			
			
			loanRepay.setNo(1);
			
			Date date = DateUtil.addMonth(now, loanInfo.getDeadline());
			loanRepay.setStartTime(now);
			loanRepay.setTime(date);
			loanRepay.setPaytime(null);
			loanRepay.setUptime(now);
			
			loanRepay.setLoanFee(loanfee);
			list.add(loanRepay);
		}
		
		
		for(LoanRepay loanRepay:list){
			this.createRepay(loanRepay);
		}
		
		
		
	}


	@Override
	public List<LoanRepay> queryByLoanId(Long loanId) {
		return loanRepayDao.queryByLoanId(loanId);
	}


	@Override
	public boolean updateForAddRepay(Long loanId, Integer no,
			Money returnAmount, Money returnPrincipal) {
		return 1==loanRepayDao.updateForAddRepay(loanId, no, returnAmount, returnPrincipal);
	}


	@Override
	public LoanRepay getByRid(Long rid) {
		return loanRepayDao.getByRid(rid);
	}

	@Override
	@Transactional(propagation=Propagation.MANDATORY)
	public LoanRepay selectForUpdateByRid(Long rid){
		return loanRepayDao.selectForUpdateByRid(rid);
	}
	
	@Override
	public boolean updateStatus(Long rid, Integer oldStatus, Integer status) {
		return 1==loanRepayDao.updateStatus(rid, oldStatus, status);
	}
	
	@Override
	public boolean updateStatus(Long loanId, Integer no, Integer oldStatus, Integer status) {
		return 1==loanRepayDao.updateStatusByLid(loanId, no,oldStatus, status);
	}
	
	@Override
	public boolean updateStatusForReturn(Long rid, Integer oldStatus, Integer status) {
		return 1==loanRepayDao.updateStatusForReturn(rid, oldStatus, status);
	}
	
	
	public PageInfo listPage(TenderRepayForm form){
		PageHelper.startPage(form.getPage(),form.getRows());
		Date startTime = null;
		Date endTime = null;
		Date startDate = null;
		Date endDate = null;
		//String tenderDate = form.getTenderDate();
		if (StringUtils.isNotBlank(form.getStartDateStr())) {
			try {
				startDate = DateUtil.parseStandardDate(form.getStartDateStr());
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		if (StringUtils.isNotBlank(form.getEndDateStr())) {
			try {
				endDate = DateUtil.parseStandardDate(form.getEndDateStr());
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		if(startDate != null){
			startTime = DateUtil.getTheDayStartTime(startDate);
		}
		if(endDate != null){
			endTime = DateUtil.getTheDayEndTime(endDate);
		}
	 
		List<LoanRepay> list = loanRepayDao.queryByStatusAndReturnTime(form.getStatus(),startTime,endTime);
		PageInfo page = new PageInfo(list);
		return page;
	}

	
/*	public LoanRepayResult doRepayForAdvance(Long loanId){
		
		LoanRepayResult loanRepayResult  = new LoanRepayResult();
		
		List<LoanRepay> repayList = this.loanRepayDao.queryByLoanIdAndStatus(loanId, LoanRepayStatus.REPAYING.getCode());
	
		
		
		if(CollectionUtils.isEmpty(repayList)){
			loanRepayResult.setResultCode(ResultCodeEnum.LoanRepay_status_error.name());
			return loanRepayResult;
		}
		
		LoanRepay earliestloanRepay = repayList.get(0);
		if(LoanRepayUtil.hasInterest(earliestloanRepay)){
			loanRepayResult.setResultCode(ResultCodeEnum.LoanRepay_has_Interest.name());
			return loanRepayResult;
		}
		
		
		
		//计算提前还款的总金额
		
		Money allRepayPrincipal= new Money();
		for(LoanRepay loanRepay:repayList){
			Money tempPrincipal = loanRepay.getPrincipal();
			allRepayPrincipal.add(tempPrincipal);
			
		}
		
		AccountTransResult tender2MiddleResult = tender2MiddleTrans(allRepayPrincipal,"还款打款");
		if(!tender2MiddleResult.isSuccess()){
			
		}
		
		//获取所有剩余的还款
		List<TenderReturn> allReturnList = new ArrayList<TenderReturn>();
		
		
		for(LoanRepay loanRepay:repayList){
			List<TenderReturn> tempList = queryTenderReturn(loanRepay);
			allReturnList.addAll(tempList);
		}
		//按投标id为key的map，投标信息里有用户的accountNo等信息
		Map<Long,Tender> tenderMap = getTenderRepaying(loanId);
		BizReturnAdvanceModel bizReturnAdvanceModel = new BizReturnAdvanceModel(repayList,allReturnList,tenderMap);
		
		//计算投资人还款的总额
		Money allReturnPrincipal = new Money();
		//按投标id分别累加单笔投资剩余未还的本金
		Map<Long,Money> allReturnPrincipalMap = new HashMap<Long,Money>(); 
		
		
		for(TenderReturn tenderReturn:allReturnList){
			allReturnPrincipal.add(tenderReturn.getPrincipal());
			Money tempMoney= allReturnPrincipalMap.get(tenderReturn.getTid());
			if(tempMoney==null){
				tempMoney = new Money();
				allReturnPrincipalMap.put(tenderReturn.getTid(), tempMoney);
			}
			tempMoney.add(tenderReturn.getPrincipal());
		}

		
	}*/
	
	/**
	 * 获取所有还款中的投标，Map格式
	 * @param loanId
	 * @return
	 *//*
	private Map<Long,Tender> getTenderRepaying(Long loanId){
		Map<Long,Tender> map = new HashMap<Long,Tender>();
		List<Tender> tenderList = tenderService.findByLoanIdAndStatus(loanId, TenderStatus.REAPYING);
		for(Tender tender:tenderList){
			map.put(tender.getTid(), tender);
		}
		return map;
	}
	private List<TenderReturn> queryTenderReturn(LoanRepay loanRepay){
		List<TenderReturn> returnList = tenderReturnService.queryByLidAndNo(loanRepay.getLid(), loanRepay.getNo());
		return returnList;
	}*/
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public LoanRepayResult doRepay2(Long loanRepayId, boolean advance,LoanInfo loanInfo) {

		LoanRepayResult result = new LoanRepayResult();
		//事物中锁住记录
		LoanRepay loanRepay = this.selectForUpdateByRid(loanRepayId);
		
		if(loanRepay==null||loanInfo==null){
			result.setResultCode(LoanRepayResult.ResultCodeEnum.LoanRepay_parameters_error.name());
			return result;
			
		}
		if(loanRepay.getStatus()!=11){
			result.setResultCode(LoanRepayResult.ResultCodeEnum.LoanRepay_status_error.name());
			return result;
		}
		//Long loanRepayId = loanRepay.getRid();

		Long lid =loanRepay.getLid();
		Integer no = loanRepay.getNo();
		
		List<TenderReturn> list = this.tenderReturnService.queryByLidAndNo(lid, no);
		
		Money allNeedReturnAmount = new Money(0L);
		Date now = new Date();
		for(TenderReturn tenderReturn:list){
			Money returnAmount = LoanRepayUtil.caluReturnAmount(tenderReturn, advance, loanInfo,now);
			allNeedReturnAmount.add(returnAmount);
		}
		
		AccountTransResult tender2MiddleResult = tender2MiddleTrans(allNeedReturnAmount,"还款打款"+loanRepay.getRid());
		if(!tender2MiddleResult.isSuccess()){
			result.setResultCode(tender2MiddleResult.getResultCode());
			return result;
		}
		Money allReturnAmount = new Money();
		Money allReturnPrincipal = new Money();
		for(TenderReturn tenderReturn:list){
			
			TenderReturnResult tenderReturnResult = tenderReturnService.doReturn(tenderReturn, advance, loanInfo,now);
			if(tenderReturnResult.isSuccess()){
				Money returnAmount = tenderReturnResult.getTenderReturn().getAmount();
				Money returnPrincipal = tenderReturnResult.getTenderReturn().getPrincipal();
				Money interest = new Money(returnAmount.getCent()-returnPrincipal.getCent());
				allReturnAmount.add(returnAmount);
				allReturnPrincipal.add(returnPrincipal);
				chargeService.doChargeForInterest(String.valueOf(tenderReturn.getUid()), interest);
				logger.info("tender return successed tenderReturn id="+tenderReturn.getId());
			}else{
				logger.error("tender return status error");
			}
			
		}
		
		//更新还款金额
		updateForAddRepay(loanRepay.getLid(), loanRepay.getNo(), allReturnAmount, allReturnPrincipal);
		//因为可能有失败的还款，所以计算成功的金额，相减获得剩余未归还的总金额还会投标归集户
		Money limitAmount = new Money(allNeedReturnAmount.getCent()-allReturnAmount.getCent());
		//如果全部正常还款，金额应该是一致的，就不会出现有剩余金额的情况
		if(limitAmount.getCent()>0){
			logger.error("limitAmount not 0:loanRepayId="+loanRepay.getRid());
			AccountTransResult middle2TenderResult = middle2TenderTrans(limitAmount,"还款剩余退回"+loanRepay.getRid());
			if(!middle2TenderResult.isSuccess()){
				/*result.setResultCode(tender2MiddleResult.getResultCode());
				return result;*/
				logger.error("middle2TenderTrans error loanRepayId="+loanRepay.getRid());
			}
		}
		if(limitAmount.getCent()==0){
			boolean repayUpdateResult = updateStatusForReturn(loanRepayId, 11, 21);
			if(repayUpdateResult==false){
				result.setResultCode(LoanRepayResult.ResultCodeEnum.LoanRepay_status_error.name());
				return result;
			}else{
				boolean isLastedLoanRepay = LoanRepayUtil.isLastedLoanRepay(loanRepay, loanInfo);
				if(isLastedLoanRepay){
					boolean loanUpdateResult = loanVariationService.updateStatusForOver(loanInfo.getLid());
					if(loanUpdateResult){
						logger.info("updateStatusForOver succesed lid="+loanInfo.getLid());
					}else{
						logger.error("updateStatusForOver fall lid="+loanInfo.getLid());
					}
				}
			}
		}else if(limitAmount.getCent()<=0){
			logger.error("limitAmount less than 0 error,loanRepayId="+loanRepay.getRid());
		}
		
		result.setSuccess(true);
		return result;
	}
	
	private AccountTransResult tender2MiddleTrans(Money amount,String memo){
		TransInfo transInfo = new TransInfo();
		transInfo.setTransCode(TransCodeEnum.TXCODE_TRANSFER);
		transInfo.setSubTransCode(SubTransCodeEnum.SUB_TRANSFER_RETURN_BATCH);
		transInfo.setTransAccountIn(InnerAccountConsts.innerMiddleAccountNo);
		transInfo.setTransAccountOut(InnerAccountConsts.innerTenderAccountNo);
		transInfo.setTransAmount(amount);
		transInfo.setTransMemo(memo);
		AccountTransResult transResult = accountTransFacade.transfer(transInfo);
		return transResult;
	}
	
	private AccountTransResult middle2TenderTrans(Money amount,String memo){
		TransInfo transInfo = new TransInfo();
		transInfo.setTransCode(TransCodeEnum.TXCODE_TRANSFER);
		//归集转账仍然用SUB_TRANSFER_TENDER
		transInfo.setSubTransCode(SubTransCodeEnum.SUB_TRANSFER_RETURN_BATCH_BACK);
		transInfo.setTransAccountIn(InnerAccountConsts.innerTenderAccountNo);
		transInfo.setTransAccountOut(InnerAccountConsts.innerMiddleAccountNo);
		transInfo.setTransAmount(amount);
		transInfo.setTransMemo(memo);
		AccountTransResult transResult = accountTransFacade.transfer(transInfo);
		return transResult;
	}

	/*public LoanRepayResult doRepayForAdvance(Long loanId, Money fine){
		
		LoanRepayResult result = new LoanRepayResult();
		
		LoanInfo loanInfo = loanInfoService.getLoanInfoById(loanId);
		
		List<LoanRepay>  list = loanRepayDao.queryByLoanIdAndStatus(loanId, 11);
		if(loanInfo.getIsFlow()==0){
			Money allRepayAmount = new Money();
			for(LoanRepay loanRepay:list){
				allRepayAmount.add(loanRepay.getPrincipal());
			}
			if(fine!=null){
				allRepayAmount.add(fine);
			}
			AccountQueryResult queryResult = this.accountQueryFacade.getAccountByUserId(String.valueOf(loanInfo.getUid()));
			boolean banlanceEnough = false;
			if(queryResult.isSuccess()){
				Money balance = queryResult.getAccountVO().getCanUserBalance();
				if(balance.getCent()<allRepayAmount.getCent()){
					banlanceEnough = true;
				}
			}
			if(!banlanceEnough){
				result.setResultCode(LoanRepayResult.ResultCodeEnum.LoanRepay_balance_not_enough.name());
				return result;
			}
		}
		
		if(list.size()==0){
			result.setResultCode(LoanRepayResult.ResultCodeEnum.LoanRepay_status_error.name());
			return result;
		}
		
		for(LoanRepay loanRepay:list){
			LoanRepayResult repayResult = doRepay(loanRepay,true,loanInfo);
			if(!repayResult.isSuccess()){
				return repayResult;
			}
		}
		
		result.setSuccess(true);
		return result;
	}*/
	
	
	public LoanRepayResult doTransRepayForAdvance(Long loanId, Money fine,boolean needRepay){
		LoanRepayResult result = new LoanRepayResult();
		
		final LoanInfo loanInfo = loanInfoService.getLoanInfoById(loanId);
		
		List<LoanRepay>  list = this.queryByLoanIdAndStatus(loanInfo.getLid(), 11);
		if(list.size()==0){
			result.setResultCode(LoanRepayResult.ResultCodeEnum.LoanRepay_status_error.name());
			return result;
		}
		if(loanInfo.getIsFlow()==0&&needRepay){
			Money allRepayAmount = new Money();
			for(LoanRepay loanRepay:list){
				Money needRepayAmount = LoanRepayUtil.caluRepayAmount(loanRepay, true, loanInfo);
				allRepayAmount.add(needRepayAmount);
			}
			if(fine!=null){
				allRepayAmount.add(fine);
			}
			AccountQueryResult queryResult = this.accountQueryFacade.getAccountByUserId(String.valueOf(loanInfo.getUid()));
			boolean banlanceEnough = false;
			String userAccountNo = null;
			if(queryResult.isSuccess()){
				Money balance = queryResult.getAccountVO().getCanUserBalance();
				userAccountNo = queryResult.getAccountVO().getAccountNo();
				if(balance.getCent()>=allRepayAmount.getCent()){
					banlanceEnough = true;
				}
			}
			if(!banlanceEnough){
				result.setResultCode(LoanRepayResult.ResultCodeEnum.LoanRepay_balance_not_enough.name());
				return result;
			}
			TransInfo transInfo = new TransInfo();
			transInfo.setTransCode(TransCodeEnum.TXCODE_TRANSFER);
			transInfo.setSubTransCode(SubTransCodeEnum.SUB_TRANSFER_REPAY);
			transInfo.setTransAccountIn(InnerAccountConsts.innerTenderAccountNo);
			transInfo.setTransAccountOut(userAccountNo);
			transInfo.setTransAmount(allRepayAmount);
			transInfo.setTransMemo("提前还款");
			AccountTransResult transResult = accountTransFacade.transfer(transInfo);
			if(transResult.isSuccess()){
				logger.info("loan Repay advance succes loan id="+loanId);
				
			}else{
				logger.error("loan Repay advance succes loan id="+loanId+" transcode= "+transResult.getResultCode());
				result.setResultCode(result.getResultCode());
				return result;
			}
		}
		
		result.setSuccess(true);
		return result;
		
	}

	public boolean doTransForLoanRepay(LoanRepay loanRepay,LoanInfo loanInfo){
		AccountQueryResult result = null;
		
		if(loanInfo.getIsFlow()==1){
			return true;
		}
		Money needRepayAmount = LoanRepayUtil.caluRepayAmount(loanRepay, false, loanInfo);
		result = accountQueryFacade.getAccountByUserId(String.valueOf(loanRepay.getUid()));
		String userAccountNo = null;
		Money balance = null;
		if(result.isSuccess()){
			userAccountNo = result.getAccountVO().getAccountNo();
			balance= result.getAccountVO().getCanUserBalance();
		}else{
			logger.error("account error when doTransForLoanRepay loanRepayId="+loanRepay.getRid());
			return false;
		}
		if(balance.getCent()<needRepayAmount.getCent()){
			logger.error("balance not enough when doTransForLoanRepay loanRepayId="+loanRepay.getRid());
			return false;
		}
		TransInfo transInfo = new TransInfo();
		transInfo.setTransCode(TransCodeEnum.TXCODE_TRANSFER);
		transInfo.setSubTransCode(SubTransCodeEnum.SUB_TRANSFER_REPAY);
		
		transInfo.setTransAccountIn(InnerAccountConsts.innerTenderAccountNo);
		transInfo.setTransAccountOut(userAccountNo);
		transInfo.setTransAmount(loanRepay.getRepayAmount());
		transInfo.setTransMemo("到期还款");
		AccountTransResult transResult = accountTransFacade.transfer(transInfo);
		if(transResult.isSuccess()){
			logger.info("loan Repay succes return id="+loanRepay.getRid());
			
			return true;
		}else{
			logger.error("loan Repay error return id="+loanRepay.getRid()+" transcode= "+transResult.getResultCode());
			return false;
		}
	}
	
	



	@Override
	public PageVo queryByTime(PageVo form) {
		List<LoanRepay> list =  loanRepayDao.queryByTime(form);
		form.setList(list);
		return form;
	}


	@Override
	public PageVo queryExceedRepayByTime(PageVo form) {
		List<LoanRepay> list =  loanRepayDao.queryExceedRepayByTime(form);
		form.setList(list);
		return form;
	}


	@Override
	public List<LoanRepay> queryByStatusAndReturnTime(Integer status,
			Date startTime, Date endTime) {
		return loanRepayDao.queryByStatusAndReturnTime(status, startTime, endTime);
	}
	
	
	
	
	/**
	 * 查询n天内即将到期的还款
	 * @param days
	 * @return
	 */
	public List<LoanRepay> queryWillExpireByDays(int days){
		Date date = DateUtil.getTheDayStartTime(new Date());
		Date startTime = DateUtil.addDay(date, 1);
		Date endTime = DateUtil.addDay(date, 1+days);
		List<LoanRepay> list =loanRepayDao.queryByStatusAndReturnTime(11, startTime, endTime);
		return list;
	}
	
	/**
	 * 查询逾期超过n天的还款
	 * @param days
	 * @return
	 */
	public List<LoanRepay> queryHasExpireOverDays(int days){
		Date date = DateUtil.getTheDayStartTime(new Date());
		
		Date endTime = DateUtil.addDay(date, -days);
		List<LoanRepay> list =loanRepayDao.queryByStatusAndReturnTime(11, null, endTime);
		return list;
	}
	
	public List<LoanRepay> queryHasExpireAndRepayed(){
		
		List<LoanRepay> list =loanRepayDao.queryByStatusAndHasExpire(21);
		return list;
	}
	
	/**
	 * 查询逾期不到n天的还款
	 * 
	 * @param days
	 * @return
	 */
	public List<LoanRepay> queryHasExpireLessDays(int days){
		Date date = DateUtil.getTheDayStartTime(new Date());		
		Date startTime = DateUtil.addDay(date, -days);		
		List<LoanRepay> list =loanRepayDao.queryByStatusAndReturnTime(11, startTime, date);
		return list;
	}
	
	public PageVo queryWillExpireByDaysPage(int days,PageVo pageVo){
		PageHelper.startPage(pageVo.getPageNum(), pageVo.getPageSize());
		List<LoanRepay> list = this.queryWillExpireByDays(days);
		pageVo.setList(list);
		
		Page page = (Page)list;
		pageVo.setTotalCount((int)page.getTotal());
		pageVo.setPages(1+(pageVo.getTotalCount()/pageVo.getPageSize()));
		return pageVo;
	}
	
	public PageVo queryHasExpireLessDaysPage(int days,PageVo pageVo){
		PageHelper.startPage(pageVo.getPageNum(), pageVo.getPageSize());
		List<LoanRepay> list = this.queryHasExpireLessDays(days);
		pageVo.setList(list);
		
		Page page = (Page)list;
		pageVo.setTotalCount((int)page.getTotal());
		pageVo.setPages(1+(pageVo.getTotalCount()/pageVo.getPageSize()));
		return pageVo;
	}
	
	public PageVo queryHasExpireOverDaysPage(int days,PageVo pageVo){
		PageHelper.startPage(pageVo.getPageNum(), pageVo.getPageSize());
		List<LoanRepay> list = this.queryHasExpireOverDays(days);
		pageVo.setList(list);
		
		Page page = (Page)list;
		pageVo.setTotalCount((int)page.getTotal());
		pageVo.setPages(1+(pageVo.getTotalCount()/pageVo.getPageSize()));
		return pageVo;
	}
	
	public PageVo queryHasExpireAndRepayedPage(PageVo pageVo){
		PageHelper.startPage(pageVo.getPageNum(), pageVo.getPageSize());
		List<LoanRepay> list = this.queryHasExpireAndRepayed();
		pageVo.setList(list);
		
		Page page = (Page)list;
		pageVo.setTotalCount((int)page.getTotal());
		pageVo.setPages(1+(pageVo.getTotalCount()/pageVo.getPageSize()));
		return pageVo;
	}


	@Override
	public List<LoanRepay> queryByLoanIdAndStatus(Long loanId, Integer status) {
		return this.loanRepayDao.queryByLoanIdAndStatus(loanId, status);
	}

}
